package entity

import (
	"gitee.com/bigmouth/quick-mock/src/domain/value"
	"gitee.com/bigmouth/quick-mock/src/infrastructure/data_operater"
	"github.com/spf13/cast"
	"html/template"
	"reflect"
	"regexp"
	"strings"
)

type MockApi struct {
	ResponseJsonDataTemplate *template.Template
	ResponseJsonDataStr      string
	Delay                    int64
	matchTypeAndRulesMap     map[value.MatchType][]MatchRule // 匹配规则
}

func NewMockApi(matchRules []MatchRule, responseJsonDataStr string, responseJsonDataTemplate *template.Template, delay int64) MockApi {
	matchRuleMap := make(map[value.MatchType][]MatchRule)
	for _, rule := range matchRules {
		if _, ok := matchRuleMap[rule.MatchType]; ok {
			rules := matchRuleMap[rule.MatchType]
			rules = append(rules, rule)
			matchRuleMap[rule.MatchType] = rules
		} else {
			matchRuleMap[rule.MatchType] = []MatchRule{rule}
		}
	}
	return MockApi{
		ResponseJsonDataStr:      responseJsonDataStr,
		ResponseJsonDataTemplate: responseJsonDataTemplate,
		Delay:                    delay,
		matchTypeAndRulesMap:     matchRuleMap,
	}
}

func (m *MockApi) GetMatchRules(t value.MatchType) []MatchRule {
	if rules, ok := m.matchTypeAndRulesMap[t]; ok {
		return rules
	}
	return make([]MatchRule, 0)
}

// IsMatchPath 匹配path
func (m *MockApi) IsMatchPath(path string) (bool, error) {
	if rules, ok := m.matchTypeAndRulesMap[value.MatchTypePath]; ok {
		for _, rule := range rules {
			if rule.Pattern == path {
				// 优先完整匹配字符串，如果相等当做匹配
				continue
			}
			isMatch, err := regexp.MatchString(rule.Pattern, path)
			if err != nil {
				return false, err
			}
			if !isMatch {
				return false, err
			}
		}
	}
	return true, nil
}

// IsMatchQueryParam 匹配url参数
func (m *MockApi) IsMatchQueryParam(queryParam map[string]string) bool {
	if rules, ok := m.matchTypeAndRulesMap[value.MatchTypeQueryParam]; ok {
		for _, rule := range rules {
			if paramValue, isExisted := queryParam[rule.DataPath]; !isExisted || paramValue != rule.Pattern {
				return false
			}
		}
	}
	return true
}

// IsMatchHeader 匹配header参数
func (m *MockApi) IsMatchHeader(header map[string]string) bool {
	if rules, ok := m.matchTypeAndRulesMap[value.MatchTypeHeader]; ok {
		for _, rule := range rules {
			if paramValue, isExisted := header[rule.DataPath]; !isExisted || paramValue != rule.Pattern {
				return false
			}
		}
	}
	return true
}

// IsMatchBodyJsonPattern 匹配body json
func (m *MockApi) IsMatchBodyJsonPattern(bodyJson map[string]interface{}) (bool, error) {
	if rules, ok := m.matchTypeAndRulesMap[value.MatchTypeBodyJsonPattern]; ok {
		for _, rule := range rules {
			pickData, err := data_operater.NewDataGetter(rule.DataPath).GetData(bodyJson)
			if err != nil {
				return false, err
			}
			vPickData := reflect.ValueOf(pickData)
			if vPickData.Kind() == reflect.Slice || vPickData.Kind() == reflect.Array {
				pickDataSlice := cast.ToStringSlice(pickData)
				pickData = strings.Join(pickDataSlice, ",")
			}
			reqData := cast.ToString(pickData)
			if reqData == rule.Pattern {
				continue
			}
			isMatch, err := regexp.MatchString(rule.Pattern, reqData)
			if err != nil {
				return false, err
			}
			if !isMatch {
				return false, nil
			}
		}
	}
	return true, nil
}

// IsMatchMethod 匹配method
// 这个方法和其他匹配不同，如果配置了多个method，只需要匹配其中一种就算匹配成功
func (m *MockApi) IsMatchMethod(method string) (bool, error) {
	method = strings.ToLower(method)
	if rules, ok := m.matchTypeAndRulesMap[value.MatchTypeMethod]; ok {
		for _, rule := range rules {
			if strings.ToLower(rule.Pattern) == method {
				// method支持多条，匹配其中一条即可
				return true, nil
			}
			isMatch, err := regexp.MatchString(rule.Pattern, method)
			if err != nil {
				return false, err
			}
			if !isMatch {
				continue
			}
		}
	}
	return false, nil
}
